package fedex;

import com.fedex.ship.stub.*;

import java.math.BigDecimal;
import java.util.Calendar;

import org.apache.axis.types.NonNegativeInteger;
import org.apache.axis.types.PositiveInteger;

//
/*
 * Sample code to call the FedEx Email label Web Service <p> com.fedex.ship.stub is generated via WSDL2Java, like this:<br> <pre> java
 * org.apache.axis.wsdl.WSDL2Java -w -p com.fedex.ship.stub http://www.fedex.com/...../ShipService?wsdl </pre> This sample code has been tested with
 * JDK 5 and Apache Axis 1.4
 */
public class FDXEmailLabelWebServiceClient {
    //
    public static void main(String[] args) {
        //
        CreatePendingShipmentRequest request = buildCreatePendingShipmentRequest();

        //
        try {
            // Initialize the service
            ShipServiceLocator service;
            ShipPortType port;
            //
            String liveurl="https://gateway.fedex.com:443/web-services";
            service = new ShipServiceLocator();
            
            //service.setShipServicePortEndpointAddress(liveurl);
            
            port = service.getShipServicePort();
            // This is the call to the web service
            CreatePendingShipmentReply reply = port.createPendingShipment(request);
            //

            if (isResponseOk(reply.getHighestSeverity())) {

                System.out.println("Customer Transaction ID: "
                        + reply.getTransactionDetail().getCustomerTransactionId());
                System.out.println("---Completed Shipment Details---");
                System.out.println("********************************");
                // Shipment Details
                CompletedShipmentDetail shipmentDetail = reply.getCompletedShipmentDetail();
                System.out.println("Url: " + shipmentDetail.getAccessDetail().getEmailLabelUrl());
                System.out.println("User Id: " + shipmentDetail.getAccessDetail().getUserId());
                System.out.println("Password: " + shipmentDetail.getAccessDetail().getPassword());
                System.out.println("Service Type Description: "
                        + shipmentDetail.getServiceTypeDescription());
                System.out.println("Packaging Description: "
                        + shipmentDetail.getPackagingDescription());
                System.out.println("Ground Service Code: " + shipmentDetail.getGroundServiceCode());
                // Package Details
                CompletedPackageDetail[] pkgs = shipmentDetail.getCompletedPackageDetails();
                System.out.println("--- Package Details ---");
                System.out.println("--------------------------------");
                for (int i = 0; i < pkgs.length; i++) {
                    CompletedPackageDetail pkg = pkgs[i];
                    TrackingId trkID = pkg.getTrackingId();
                    String formId = trkID.getFormId();
                    String trkNumber = trkID.getTrackingNumber();
                    SignatureOptionType signatureOption = pkg.getSignatureOption();
                    String signatureOptionStr = signatureOption.getValue();
                    PositiveInteger sequenceNbr = pkg.getSequenceNumber();

                    System.out.println("Tracking Number: " + trkNumber);
                    System.out.println("Form Id: " + formId);
                    System.out.println("Signature Option: " + signatureOptionStr);
                    System.out.println("Sequence Number: " + sequenceNbr.longValue());
                }
                System.out.println("--------------------------------");
                System.out.println("********************************");
            }else{
                System.out.println("!!!!!!!!!!!!!! Error!!!!!!!!!!!!");
            }

            printNotifications(reply.getNotifications());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static CreatePendingShipmentRequest buildCreatePendingShipmentRequest() {
        CreatePendingShipmentRequest request = new CreatePendingShipmentRequest();

        request.setClientDetail(createClientDetail());
        request.setWebAuthenticationDetail(createWebAuthenticationDetail());
        //
        VersionId versionId = new VersionId("ship", 6, 0, 0);
        request.setVersion(versionId);
        //
        TransactionDetail transactionDetail = new TransactionDetail();
        transactionDetail.setCustomerTransactionId("java sample - FDXEmailLabelRequest"); //This is a reference field for the customer.  Any value can be used and will be provided in the return.
        request.setTransactionDetail(transactionDetail);

        request.setRequestedShipment(buildRequestedShipment());

        return request;
    }

    private static RequestedShipment buildRequestedShipment() {
        RequestedShipment requestedShipment = new RequestedShipment();
        requestedShipment.setShipTimestamp(Calendar.getInstance()); // Ship date and time
        requestedShipment.setDropoffType(DropoffType.REGULAR_PICKUP); // Dropoff Types are BUSINESS_SERVICE_CENTER, DROP_BOX, REGULAR_PICKUP, REQUEST_COURIER, STATION
        requestedShipment.setServiceType(ServiceType.PRIORITY_OVERNIGHT); // Service types are STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND ...
        requestedShipment.setPackagingType(PackagingType.YOUR_PACKAGING); // Packaging type FEDEX_BOK, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING, ...
        
        Weight weight = new Weight(); // Total weight information
        weight.setValue(new BigDecimal(100.0));
        weight.setUnits(WeightUnits.LB);
        requestedShipment.setTotalWeight(weight);
        
        //
        Party shipperParty = new Party(); // Sender information
        Contact shipperContact = new Contact();
        shipperContact.setPersonName("Sender Name");
        //shipperContact.setCompanyName("Sender Company Name");
        shipperContact.setPhoneNumber("0805522713");
        Address shipperAddress = new Address();
        String[] tempStreet = new String[1];
        tempStreet[0] = "Address Line 1";
        shipperAddress.setStreetLines(tempStreet);
        shipperAddress.setCity("Austin");
        shipperAddress.setStateOrProvinceCode("TX");
        shipperAddress.setPostalCode("73301");
        //Origin country code must be US for return shipments
        shipperAddress.setCountryCode("US");
        shipperParty.setContact(shipperContact);
        shipperParty.setAddress(shipperAddress);
        requestedShipment.setShipper(shipperParty);
        //
        Party recipientParty = new Party(); // Recipient information
        Contact recipientContact = new Contact();
        recipientContact.setPersonName("Recipient Name");
        recipientContact.setCompanyName("Recipient Company Name");
        //901-263-9999
        recipientContact.setPhoneNumber("901-263-9999");
        Address recipientAddress = new Address();
        tempStreet[0] = "Address Line 1";
        recipientAddress.setStreetLines(tempStreet);
        recipientAddress.setCity("Windsor");
        recipientAddress.setStateOrProvinceCode("CT");
        recipientAddress.setPostalCode("06006");
        //Destination country code must be US for return shipments
        recipientAddress.setCountryCode("US");
        recipientAddress.setResidential(Boolean.valueOf(true));
        recipientParty.setContact(recipientContact);
        recipientParty.setAddress(recipientAddress);
        requestedShipment.setRecipient(recipientParty);

        //
        Payment payment = new Payment(); // Payment information
        payment.setPaymentType(PaymentType.SENDER);
        
        Payor payor = new Payor();
        // See if Payor Account number property is set, if not default to "XXX"
        String payorAccountNumber ="510087488";// System.getProperty("Payor.AccountNumber");
        

        payor.setAccountNumber(payorAccountNumber);
        payor.setCountryCode("US");
        payment.setPayor(payor);
        
        requestedShipment.setShippingChargesPayment(payment);
        //
        
        requestedShipment.setRequestedPackages(new RequestedPackage[] { new RequestedPackage() });
        requestedShipment.getRequestedPackages(0).setSpecialServicesRequested(
                new PackageSpecialServicesRequested());
        requestedShipment.getRequestedPackages(0).getSpecialServicesRequested().setDryIceWeight(
                new Weight(WeightUnits.LB, new BigDecimal(10.0)));
                
        //
        LabelSpecification labelSpecification = new LabelSpecification(); // Label specification	    
        labelSpecification.setImageType(ShippingDocumentImageType.PDF);// Image types PDF, PNG, DPL, ...	
        labelSpecification.setLabelFormatType(LabelFormatType.COMMON2D); //LABEL_DATA_ONLY, COMMON2D
        requestedShipment.setLabelSpecification(labelSpecification);
        //
        RateRequestType rateRequestType[] = new RateRequestType[1];
        rateRequestType[0] = RateRequestType.ACCOUNT; // Rate types requested LIST, MULTIWEIGHT, ...
        requestedShipment.setRateRequestTypes(rateRequestType);
        
        int count=2;
        
        requestedShipment.setPackageCount(new NonNegativeInteger(""+count));
        RequestedPackage rp[] = new RequestedPackage[count];
        Weight rpWeight = new Weight(); // Package weight information
        rpWeight.setValue(new BigDecimal(12.0));
        rpWeight.setUnits(WeightUnits.LB);
        for(int i=1;i<=count;i++)
        {
        //
        rp[i-1] = new RequestedPackage();
        rp[i-1].setWeight(rpWeight);
        rp[i-1].setItemDescription("Test lable desc.12345_"+i);
        rp[i-1].setSequenceNumber(new PositiveInteger(""+i));
        // 
        }
        requestedShipment.setRequestedPackages(rp);
        requestedShipment.setSpecialServicesRequested(createSpecialService());

        return requestedShipment;
    }

    private static ShipmentSpecialServicesRequested createSpecialService() {
        ShipmentSpecialServicesRequested specialService = new ShipmentSpecialServicesRequested();
        ShipmentSpecialServiceType[] specialServiceTypes = new ShipmentSpecialServiceType[2];
        specialServiceTypes[0] = ShipmentSpecialServiceType.RETURN_SHIPMENT;
        specialServiceTypes[1] = ShipmentSpecialServiceType.PENDING_SHIPMENT;
        specialService.setSpecialServiceTypes(specialServiceTypes);

        ReturnShipmentDetail returnShipmentDetail = new ReturnShipmentDetail();
        ReturnType returnType = ReturnType.PENDING;
        returnShipmentDetail.setReturnType(returnType);

        returnShipmentDetail.setRma(new Rma("[rma987654]", "RMA Reason"));

        ReturnEMailDetail returnEMailDetail = new ReturnEMailDetail();
        //901-263-9999
        returnEMailDetail.setMerchantPhoneNumber("901-263-9999");
        ReturnEMailAllowedSpecialServiceType[] allowedSpecialServices =
                new ReturnEMailAllowedSpecialServiceType[] { ReturnEMailAllowedSpecialServiceType.SATURDAY_DELIVERY };
        returnEMailDetail.setAllowedSpecialServices(allowedSpecialServices);

        returnShipmentDetail.setReturnEMailDetail(returnEMailDetail);

        EMailLabelDetail emailLabelDetail = new EMailLabelDetail();
        //invalid@none.fedex.com customer email address
        emailLabelDetail.setNotificationEMailAddress("aweisw@gmail.com");
        emailLabelDetail.setNotificationMessage("");

        PendingShipmentDetail pendingShipmentDetail = new PendingShipmentDetail();
        pendingShipmentDetail.setType(PendingShipmentType.EMAIL);
        java.util.Date expirationDate = new java.util.Date();
        pendingShipmentDetail.setExpirationDate(expirationDate);
        pendingShipmentDetail.setEmailLabelDetail(emailLabelDetail);

        EMailNotificationDetail eMailNotificationDetail = new EMailNotificationDetail();
        eMailNotificationDetail.setPersonalMessage("");
        EMailNotificationRecipient[] recipients = new EMailNotificationRecipient[1];
        recipients[0] = new EMailNotificationRecipient();
        //recipient@company.com
        recipients[0].setEMailAddress("recipient@company.com");
        recipients[0].setEMailNotificationRecipientType(EMailNotificationRecipientType.BROKER);
        recipients[0].setFormat(EMailNotificationFormatType.HTML);
        recipients[0].setLocalization(new Localization("ENGLISH", "US"));
        recipients[0].setNotifyOnDelivery(new Boolean(true));
        recipients[0].setNotifyOnException(new Boolean(true));
        recipients[0].setNotifyOnShipment(new Boolean(true));
        eMailNotificationDetail.setRecipients(recipients);
        specialService.setEMailNotificationDetail(eMailNotificationDetail);

        specialService.setPendingShipmentDetail(pendingShipmentDetail);
        specialService.setReturnShipmentDetail(returnShipmentDetail);
        return specialService;
    }

    private static ClientDetail createClientDetail() {
        ClientDetail clientDetail = new ClientDetail();
        String accountNumber = "xx";
        String meterNumber = "xx";
        clientDetail.setAccountNumber(accountNumber);
        clientDetail.setMeterNumber(meterNumber);
        return clientDetail;
    }

    private static WebAuthenticationDetail createWebAuthenticationDetail() {
        WebAuthenticationCredential wac = new WebAuthenticationCredential();
        String key ="xx";
        String password ="xx";
        
        wac.setKey(key);
        wac.setPassword(password);
        return new WebAuthenticationDetail(wac);
    }

    private static void printNotifications(Notification[] notifications) {
        System.out.println("Notifications:");
        if (notifications == null || notifications.length == 0) {
            System.out.println("  No notifications returned");
        }
        for (int i = 0; i < notifications.length; i++) {
            Notification n = notifications[i];
            System.out.print("  Notification no. " + i + ": ");
            if (n == null) {
                System.out.println("null");
                continue;
            } else {
                System.out.println("");
            }
            NotificationSeverityType nst = n.getSeverity();

            System.out.println("    Severity: " + (nst == null ? "null" : nst.getValue()));
            System.out.println("    Code: " + n.getCode());
            System.out.println("    Message: " + n.getMessage());
            System.out.println("    Source: " + n.getSource());
        }
    }

    private static boolean isResponseOk(NotificationSeverityType notificationSeverityType) {
        if (notificationSeverityType == null) {
            return false;
        }
        if (notificationSeverityType.equals(NotificationSeverityType.WARNING)
                || notificationSeverityType.equals(NotificationSeverityType.NOTE)
                || notificationSeverityType.equals(NotificationSeverityType.SUCCESS)) {
            return true;
        }
        return false;
    }

    private static void updateEndPoint(ShipServiceLocator serviceLocator) {
        String endPoint = System.getProperty("endPoint");
        if (endPoint != null) {
            serviceLocator.setShipServicePortEndpointAddress(endPoint);
        }
    }
}
